﻿
// ## 2022/12/11 # 铃 # 运输队特殊情况的调整策略

namespace AI运输队调整
{

	/// =========================================================================================

	const bool 调试模式 = false;
	const bool 调试模式2 = false;


	const int KEY = pk::hash("AI运输队调整");

	class Main
	{
		Main()
		{
			pk::bind(111, pk::trigger111_t(onTurnStart));
		}

		void onTurnStart(pk::force @force)
		{
			if (!pk::is_normal_force(force) or force.get_id() >= 势力_末 or force.get_id() < 0)
				return;

			
			pk::list<pk::unit @> unit_list = pk::get_unit_list(force);
			for (int i = 0; i < unit_list.count; i++)
			{
				pk::unit @unit = unit_list[i];
				if (!pk::is_alive(unit))
					continue;

				//  跳过非运输类型部队
				if (unit.type != 部队类型_运输)
					continue;

				if ((unit.order == 部队任务_待命))
				{
					func_重设运输队目标(unit);
					continue;
				}

				if ((unit.target_type == 部队任务对象_据点) and pk::is_valid_base_id(unit.target) and unit.target < 据点_末)
				{
					if (unit.troops + pk::get_troops(pk::get_building(unit.target)) > pk::get_max_troops(pk::get_building(unit.target)) + 1000) //允许1000的冗余
						func_重设运输队目标(unit);
					continue;

				}

			}

		}


		void func_重设运输队目标(pk::unit @unit)
		{

			array<pk::building @> dst_base_arr = 获取目标据点列表(unit);
			int dst_id;

			if (dst_base_arr.length == 0)
			{
				pk::person@ leader = pk::get_person(unit.leader);
				 dst_id = leader.service;
				if (dst_id < 0 or dst_id >据点_末)
					return;
				pk::set_order(unit, 部队任务_撤退, pk::get_building(leader.service).pos);

			}

			else
			{
			// 运输候选据点的优先顺序
				dst_base_arr.sort(function(a, b) { return main.比较运输据点(a, b); });
				pk::set_order(unit, 部队任务_移动, dst_base_arr[0].pos);
				dst_id = dst_base_arr[0].get_id();
			}

			pk::building @dst_base = pk::get_building(dst_id);


			if (调试模式)
			{
				string unit_name = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(unit)));
				string dst_base_name2 = pk::format("\x1b[1x{}\x1b[0x", pk::decode(pk::get_name(dst_base)));
				string action_message = pk::format("{}修改运输任务到{}", unit_name, dst_base_name2);
				pk::trace(action_message);
			}

			return;


		}


		// 查找可用据点
		array<pk::building @> 获取目标据点列表(pk::unit @unit)
		{

			array<pk::building @> dst_base_arr;
			for (int i = 0; i < 据点_末; i++)
			{

				pk::building @dst_base = pk::get_building(i);

				if (!pk::is_alive(dst_base))
					continue;

				//满的据点跳过
				if (pk::get_troops(dst_base) + unit.troops > pk::get_max_troops(dst_base) + 1000)//允许1000的冗余
					continue;

				//太远不行
				if (pk::get_distance(dst_base.pos, unit.pos) > 30)
					continue;

				//判断势力
				if (dst_base.get_force_id() != unit.get_force_id())
					continue;

				dst_base_arr.insertLast(dst_base);
			}

			return dst_base_arr;
		}

		int 附近敌方据点数量(pk::building @building, int distance)
		{
			int enemy_building_count = 0;
			for (int i = 0; i < 据点_末; i++)
			{
				pk::building @neighbor_building = pk::get_building(i);
				int distanceToBuilding = pk::get_building_distance(building.get_id(), i, building.get_force_id());
				if (distanceToBuilding > distance)
					continue;
				if (!pk::is_enemy(building, neighbor_building))
					continue;
				enemy_building_count++;
			}
			return enemy_building_count;
		}

		int 附近敌方据点兵力(pk::building @building, int distance)
		{
			int enemy_troops_count = 0;
			for (int i = 0; i < 据点_末; i++)
			{
				pk::building @neighbor_building = pk::get_building(i);
				int distanceToBuilding = pk::get_building_distance(building.get_id(), i, building.get_force_id());
				if (distanceToBuilding > distance)
					continue;
				if (!pk::is_enemy(building, neighbor_building))
					continue;
				enemy_troops_count += pk::get_max_marchable_troops(neighbor_building);
			}
			return enemy_troops_count;
		}

				// 使用多因子模型比较需要输送的据点之间的优先级
		bool 比较运输据点(pk::building @building_a, pk::building @building_b)
		{
			float score_a = 0.f;
			float score_b = 0.f;
			int 一格据点数量_a = 0;
			int 一格据点数量_b = 0;
			int 二格据点数量_a = 0;
			int 二格据点数量_b = 0;
			int 三格据点数量_a = 0;
			int 三格据点数量_b = 0;

			int 一格据点兵力_a = 0;
			int 一格据点兵力_b = 0;
			int 二格据点兵力_a = 0;
			int 二格据点兵力_b = 0;
			int 三格据点兵力_a = 0;
			int 三格据点兵力_b = 0;


			for (int i = 0; i < 据点_末; i++)
			{
				pk::building @neighbor_building = pk::get_building(i);

				if (pk::get_building_distance(building_a.get_id(), i, building_a.get_force_id()) == 1 and pk::is_enemy(building_a, neighbor_building))
				{
					一格据点数量_a++;
					一格据点兵力_a += pk::get_troops(neighbor_building);
				}

				if (pk::get_building_distance(building_a.get_id(), i, building_a.get_force_id()) == 2 and pk::is_enemy(building_a, neighbor_building))
				{
					二格据点数量_a++;
					二格据点兵力_a += pk::get_troops(neighbor_building);
				}

				if (pk::get_building_distance(building_a.get_id(), i, building_a.get_force_id()) == 3 and pk::is_enemy(building_a, neighbor_building))
				{
					三格据点数量_a++;
					三格据点兵力_a += pk::get_troops(neighbor_building);
				}


				if (pk::get_building_distance(building_b.get_id(), i, building_b.get_force_id()) == 1 and pk::is_enemy(building_b, neighbor_building))
				{
					一格据点数量_b++;
					一格据点兵力_b += pk::get_troops(neighbor_building);
				}

				if (pk::get_building_distance(building_b.get_id(), i, building_b.get_force_id()) == 2 and pk::is_enemy(building_b, neighbor_building))
				{
					二格据点数量_b++;
					二格据点兵力_b += pk::get_troops(neighbor_building);
				}

				if (pk::get_building_distance(building_b.get_id(), i, building_b.get_force_id()) == 3 and pk::is_enemy(building_b, neighbor_building))
				{
					三格据点数量_b++;
					三格据点兵力_b += pk::get_troops(neighbor_building);
				}

			}
						// 因子1:据点前线状态：敌人据点越多的优先级越高
			score_a += 一格据点兵力_a * 5;
			score_b += 一格据点兵力_b * 5;

			score_a += 二格据点兵力_a * 3;
			score_b += 二格据点兵力_b * 3;

			score_a += 三格据点兵力_a * 2;
			score_b += 三格据点兵力_b * 2;

			// 因子2:据点前线状态：敌军兵力越多的优先级越高
			score_a += 一格据点数量_a * 5;
			score_b += 一格据点数量_b * 5;

			score_a += 二格据点数量_a * 3;
			score_b += 二格据点数量_b * 3;

			score_a += 三格据点数量_a * 2;
			score_b += 三格据点数量_b * 2;


			// 因子4:据点自身兵力,越少优先级越高
			score_a -= pk::get_troops(building_a) / 30000.f;
			score_b -= pk::get_troops(building_b) / 30000.f;

			// 因子4:据点所属自身兵力,越少优先级越高
			score_a -= pk::get_max_marchable_troops(building_a) / 30000.f;
			score_b -= pk::get_max_marchable_troops(building_b) / 30000.f;

			// 因子5:据点资金,越少优先级越高
			score_a -= pk::get_gold(building_a) / 50000.f;
			score_b -= pk::get_gold(building_b) / 50000.f;

			// 因子6:据点兵粮,越少优先级越高
			score_a -= pk::get_food(building_a) / 100000.f;
			score_b -= pk::get_food(building_b) / 100000.f;

			// 因子7:据点兵装,越少优先级越高
			score_a -= (pk::get_max_weapon_amount(building_a, 1) + pk::get_max_weapon_amount(building_a, 2) + pk::get_max_weapon_amount(building_a, 3) + pk::get_max_weapon_amount(building_a, 4)) / 100000.f;
			score_b -= (pk::get_max_weapon_amount(building_b, 1) + pk::get_max_weapon_amount(building_b, 2) + pk::get_max_weapon_amount(building_b, 3) + pk::get_max_weapon_amount(building_b, 4)) / 100000.f;

			// 因子8:大城天然分高
			if (building_a.get_id() >= 城市_末) score_a /= 5;
			if (building_b.get_id() >= 城市_末) score_b /= 5;

			// 因子8:大城天然分高
			if (building_a.get_id() >= 城市_末 and ch::neibor_enemy_base_count(building_a, 1) == 0) score_a /= 5;
			if (building_b.get_id() >= 城市_末 and ch::neibor_enemy_base_count(building_b, 1) == 0) score_b /= 5;

			return score_a > score_b;
		}
	} Main main;

}